# -*- coding: utf-8 -*-
from datetime import datetime
from io import BytesIO
from lib.qiniucloud.qiniuMain import QiNiuService
import os

from docx import Document
from docx.shared import RGBColor
from docx.shared import Inches
from docx.shared import Pt
import re
import requests
import shutil

TMP_PATH = os.path.abspath('../../elephant_tmp')
# service 对应/home/yjyx/elephant_tmp
TEMPLATE_FILE = os.path.abspath('lib/docx/yj_elephant_template.docx')
TEACHER_TEMPLATE_FILE = os.path.abspath('lib/docx/yj_teacher_template.docx')


class SimpleDocxService:
    def __init__(self, template=TEMPLATE_FILE):
        self.document = Document(template)
        self.paragraphs = self.document.paragraphs
        self.qiniu = QiNiuService('doc')

    def temp_fold(self, cpath):
        path = os.path.join(TMP_PATH, cpath)
        if not os.path.exists(path):
            os.makedirs(path)
        return path

    def set_normal_font(self, name, size):
        font = self.document.styles['Normal'].font
        font.name = name
        font.size = Pt(size)

    def add_head(self, text, lv):
        self.document.add_heading(text, level=lv)

    def fill_information(self, user_name, phone, questions='0', similar='0'):
        create_time = datetime.now().strftime("%Y-%m-%d")
        self.paragraphs[2].text = self.paragraphs[2].text.replace(
            '{user_name}', user_name).replace(
            '{create_time}', create_time).replace(
            '{phone}', phone
        )
        self.paragraphs[3].text = self.paragraphs[3].text.replace('{questions}', questions).replace('{similar}', similar)

    def open_text(self):

        class Paragraph:
            def __init__(self, paragraph):
                self.paragraph = paragraph
                self.text = None

            def __enter__(self):
                return self

            def add(self, text):
                self.text = self.paragraph.add_run(text)
                return self

            def italic(self):
                self.text.italic = True
                return self

            def bold(self):
                self.text.bold = True
                return self

            def color(self, r, g, b):
                self.text.font.color.rgb = RGBColor(r, g, b)
                return self

            def close(self):
                del self.paragraph
                del self.text

            def __exit__(self, *args):
                self.close()

        return Paragraph(self.document.add_paragraph())

    def add_picture(self, filename, inch):
        self.document.add_picture(filename, width=Inches(inch))

    def add_picture_bin(self, steam):
        self.document.add_picture(steam)

    def upload_doc(self, filename):
        _, _, file_url = self.qiniu.upload_file(filename)
        return file_url

    def del_folder(self, folder):
        shutil.rmtree(folder)

    def del_file(self, file):
        os.remove(file)

    def save(self, name):
        self.document.save(name)


class TeacherDocxService(SimpleDocxService):

    def __init__(self):
        super().__init__(TEACHER_TEMPLATE_FILE)

    def fill_information_teacher(self, class_name, questions='0'):
        create_time = datetime.now().strftime("%Y-%m-%d")
        self.paragraphs[2].text = self.paragraphs[2].text.replace(
            '{class_name}', class_name).replace(
            '{create_time}', create_time)
        self.paragraphs[3].text = self.paragraphs[3].text.replace('{questions}', questions)


def create_doc(e_q, s_q, similar_q, user_name, phone, user_id):
    """
    :param e_q: 大象自拍题 []
    :param s_q: 系统题 []
    :param similar_q: 类似题 []
    :return:
    """
    try:
        # 类似题数量
        similar_q_count = str(len(similar_q))
        # 系统题+自拍题数量
        s_q_count = str(len(s_q) + len(e_q))
        # 系统题+类似题集合
        s_q.extend(similar_q)
        time_now = datetime.now().strftime("%Y-%m-%d")
        docx = SimpleDocxService()
        docx.fill_information(user_name, phone, questions=s_q_count, similar=similar_q_count)
        folder_name = "{user_id}_{create_time}".format(user_id=user_id, create_time=time_now)
        folder_path = docx.temp_fold(folder_name)
        doc_name = os.path.join(folder_path, "".join([folder_name, ".docx"]))
        if e_q:
            docx.add_head("自拍题", 2)
            for index, img_list in enumerate(e_q, start=1):
                # file ways:
                # docx.open_text().add("%s." % index)
                # response = requests.get(img, stream=True)
                # img_name = os.path.join(folder_path, str(index)+'.png')
                # with open(img_name, 'wb') as out_file:
                #     shutil.copyfileobj(response.raw, out_file)
                # ----------------------------------
                # stream ways:
                docx.open_text().add("%s." % index)
                for img in img_list:
                    response = requests.get(img)
                    binary_img = BytesIO(response.content)
                    docx.add_picture(binary_img, 6.0)
        if s_q:
            docx.add_head("错题&类似题", 2)
            for index, content in enumerate(s_q, start=1):
                docx.open_text().add("%s." % index)
                # p re
                p_reg = r"<p.*?>([\s\S]*?)<\/p>"
                # u re
                u_reg = r"<u.*?>([\s\S]*?)<\/u>"
                # 需要批量替换空的标签，span， dive
                blank_reg = [r"<span.*?>", r"<\/span>", r"<div.*?>", r"<\/div>"]

                # 替换p标签
                if re.match(p_reg, content):
                    content = "\n".join(re.findall(p_reg, content))
                # 替换u标签, u标签为下划线，默认替换为3个下划线
                content = re.sub(u_reg, "___", content)
                # 替换span标签为空, 替换div
                for each in blank_reg:
                    content = re.sub(each, "", content)
                # if re.match(span_reg, content):
                #     content = "".join(re.findall(span_reg, content))
                # content = content.replace("<p>", "").replace("</p>", "").replace("&nbsp;", " ")
                # 替换html中空格
                content = content.replace("&nbsp;", " ")
                # 替换连续的\n换行符
                content = re.sub(r"\n{2,}", "\n", content)
                # 去掉文本首个换行符以及制表符
                content = re.sub(r"^\n\t", "", content)
                content = re.sub(r"^\n", "", content)
                # 筛选出所有img标签的src值，即图片地址
                img_obj = re.findall(r'<img.*?src="(.*?)".*?/>', content)
                # 替换所有img标签内容成{img}
                content = re.sub(r"<img[^>]*/>", "{img}", content)
                if img_obj:
                    # 如果存在img，则split文本，分片插入文本
                    for index, item in enumerate(content.split("{img}")):
                        docx.open_text().add(item)
                        # 正常img的长度要比content的长度小1，故判断索引=文本切片-1则意味着没有图片可以取，直接结束循环
                        if index == len(content.split("{img}")) - 1:
                            break
                        else:
                            # response = requests.get(img_obj[index], stream=True)
                            # img_name = os.path.join(folder_path, str(index)+'.png')
                            # with open(img_name, 'wb') as out_file:
                            #     shutil.copyfileobj(response.raw, out_file)
                            # docx.add_picture(img_name, 1.0)
                            # stream way
                            response = requests.get(img_obj[index], stream=True)
                            binary_img = BytesIO(response.content)
                            docx.add_picture(binary_img, 1.0)
                else:
                    docx.open_text().add(content)
        docx.save(doc_name)
        doc_url = docx.upload_doc(doc_name)
        # 删除文件而且不是文件夹
        # docx.del_folder(folder_path)
        docx.del_file(doc_name)

    except Exception as e:
        return e
    return doc_url


def create_doc_teacher(e_q, s_q, similar_q, class_name, user_id):
    """
    :param e_q: 大象自拍题 []
    :param s_q: 系统题 []
    :param similar_q: 类似题 []
    :return:
    """
    try:
        # 系统题+自拍题数量
        s_q_count = str(len(s_q) + len(e_q))
        # 系统题+类似题集合
        s_q.extend(similar_q)
        time_now = datetime.now().strftime("%Y-%m-%d")
        docx = TeacherDocxService()
        docx.fill_information_teacher(class_name, questions=s_q_count)
        folder_name = "{user_id}_{create_time}".format(user_id=user_id, create_time=time_now)
        folder_path = docx.temp_fold(folder_name)
        doc_name = os.path.join(folder_path, "".join([folder_name, ".docx"]))
        if e_q:
            for index, img_list in enumerate(e_q, start=1):
                # file ways:
                # docx.open_text().add("%s." % index)
                # response = requests.get(img, stream=True)
                # img_name = os.path.join(folder_path, str(index)+'.png')
                # with open(img_name, 'wb') as out_file:
                #     shutil.copyfileobj(response.raw, out_file)
                # ----------------------------------
                # stream ways:
                docx.open_text().add("%s." % index)
                for img in img_list:
                    response = requests.get(img)
                    binary_img = BytesIO(response.content)
                    docx.add_picture(binary_img, 6.0)
        if s_q:
            for index, content in enumerate(s_q, start=1):
                docx.open_text().add("%s." % index)
                # p re
                p_reg = r"<p.*?>([\s\S]*?)<\/p>"
                # u re
                u_reg = r"<u.*?>([\s\S]*?)<\/u>"
                # 需要批量替换空的标签，span， dive
                blank_reg = [r"<span.*?>", r"<\/span>", r"<div.*?>", r"<\/div>"]

                # 替换p标签
                if re.match(p_reg, content):
                    content = "\n".join(re.findall(p_reg, content))
                # 替换u标签, u标签为下划线，默认替换为3个下划线
                content = re.sub(u_reg, "___", content)
                # 替换span标签为空, 替换div
                for each in blank_reg:
                    content = re.sub(each, "", content)
                # if re.match(span_reg, content):
                #     content = "".join(re.findall(span_reg, content))
                # content = content.replace("<p>", "").replace("</p>", "").replace("&nbsp;", " ")
                # 替换html中空格
                content = content.replace("&nbsp;", " ")
                # 替换连续的\n换行符
                content = re.sub(r"\n{2,}", "\n", content)
                # 去掉文本首个换行符以及制表符
                content = re.sub(r"^\n\t", "", content)
                content = re.sub(r"^\n", "", content)
                # 筛选出所有img标签的src值，即图片地址
                img_obj = re.findall(r'<img.*?src="(.*?)".*?/>', content)
                # 替换所有img标签内容成{img}
                content = re.sub(r"<img[^>]*/>", "{img}", content)
                if img_obj:
                    # 如果存在img，则split文本，分片插入文本
                    for index, item in enumerate(content.split("{img}")):
                        docx.open_text().add(item)
                        # 正常img的长度要比content的长度小1，故判断索引=文本切片-1则意味着没有图片可以取，直接结束循环
                        if index == len(content.split("{img}")) - 1:
                            break
                        else:
                            # response = requests.get(img_obj[index], stream=True)
                            # img_name = os.path.join(folder_path, str(index)+'.png')
                            # with open(img_name, 'wb') as out_file:
                            #     shutil.copyfileobj(response.raw, out_file)
                            # docx.add_picture(img_name, 1.0)
                            # stream way
                            response = requests.get(img_obj[index], stream=True)
                            binary_img = BytesIO(response.content)
                            docx.add_picture(binary_img, 1.0)
                else:
                    docx.open_text().add(content)
        docx.save(doc_name)
        doc_url = docx.upload_doc(doc_name)
        # 删除文件而且不是文件夹
        # docx.del_folder(folder_path)
        docx.del_file(doc_name)

    except Exception as e:
        return e
    return doc_url
